{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# More on Using NER to Map Geographic Metadata in MARC Records\n",
    "*Now with a **better** strategy for disambiguating placenames!*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This post follows up on a previous posts about using NER to map placenames found in ISAW Library MARC records. One problem that we encountered in the last post was the disambiguation of placename data. \n",
    "\n",
    "To summarize the work completed so far: using the American School of Classical Studies at Athens's 1947 [*Ancient Corinth: A guide to the excavations*](http://www.worldcat.org/title/ancient-corinth-a-guide-to-the-excavations/oclc/10220993), we can use the Stanford NER tagger to return possible location-topics for the book—in this case, Corinth (thankfully!), Athens, and Greece. Using Geonames, we can get a list of possible matches for these places, retrieve the latitude and longitude data, and map these points. That said, a query for 'athens' yields both \"Athens, Greece\" and \"Athens, GA\" so some disambiguation strategy is necessary.\n",
    "\n",
    "In this notebook, I use geographic clustering with DBSCAN to isolate a 'region' for the coordinates that best suits the original research question: \"Where is this book about?\" Using a threshold of 1000km, the cities of Athens and Corinth and the country of Greece all fall into one cluster, while Athens, GA falls into another (and, for that matter, Corinth in Saint Lucia into yet another). Assuming that a book is geographically coherent—a large and problematic assumption, though perhaps less so for an archaeological site report—we work from the premise that the highest frequency locations will cluster together. From here (for now), we take the closest coordinates to the cluster's center. As shown below, this strategy works for *Ancient Corinth*. More testing is neeeded, but this experiment is encouraging and it moves the solution to our disambiguation problem further along. [PJB 6.22.18]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Imports\n",
    "\n",
    "import os\n",
    "\n",
    "import xml.etree.ElementTree as ET\n",
    "import json\n",
    "import requests\n",
    "\n",
    "from collections import Counter, defaultdict\n",
    "import random\n",
    "\n",
    "from nltk.tag import StanfordNERTagger\n",
    "from nltk.tokenize import word_tokenize\n",
    "from nltk import pos_tag\n",
    "from nltk.chunk import conlltags2tree\n",
    "from nltk.tree import Tree\n",
    "\n",
    "import folium\n",
    "\n",
    "from pprint import pprint\n",
    "from tqdm import tqdm #for progress bar\n",
    "\n",
    "# Constants\n",
    "isbn_valid = '0123456789xX'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set environment variable\n",
    "# Geonames requires a username to access the API but we do not want to expose personal info in code\n",
    "# Run this locally by adding USERNAME to environment variables, e.g. to .env, as follows:\n",
    "# > export USERNAME=<insert username here>\n",
    "USERNAME = os.getenv('USERNAME')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get MARC Records"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Sample BSN; BSN is a code that NYU Libraries use to identify books in the collection\n",
    "# This is the BSN for... \n",
    "# \"Ancient Corinth: A guide to the excavations,\" O. Broneer, R. Carpenter, and C. H. Morgan\n",
    "\n",
    "bsns = ['003442638']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Request MARC records for each BSN\n",
    "# NB: Only works on the NYU network; I provide sample output as a string in the example\n",
    "# NB: This notebook takes the MARC XML and reduces it to a single string; it would probably be better\n",
    "# to isolate only the subject headings (and perhaps the title). Without doing this, NER is going to pick\n",
    "# up the imprint information as well.\n",
    "\n",
    "# marcs = []\n",
    "\n",
    "# for bsn in tqdm(bsns):\n",
    "#     urlstring = 'http://aleph.library.nyu.edu/X?op=publish_avail&library=nyu01&doc_num=%s' % bsn\n",
    "#     aleph_request = requests.get(urlstring)\n",
    "#     aleph_string = aleph_request.text\n",
    "#     tree = ET.fromstring(aleph_string)\n",
    "#     marc = \" \".join(ET.tostring(tree, encoding='utf8', method='text').decode('utf-8').split('\\n')).strip()\n",
    "#     marcs.append(marc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['aleph-publish:003442638    00000cam a2200421 a 4500 BK 00000cam a2200421 a 4500 003442638 OCoLC 20110421131315.0 110421s1947    gr aef        000 0 eng d  (OCoLC)10220993   CIN eng CIN OCL OCLCQ OCLCG OCLCA OCLCQ NNU   eng   e-gr---   DF261.C65 A57 1947   (OCoLC)10220993   Ancient Corinth : a guide to the excavations.   Guide to the excavations of ancient Corinth   4th ed., rev. and enl.   [Athens? : Printing Office \"Hestia\"], 1947.   127 p., [2] leaves of plates : ill., plans (some fold.) ; 21 cm.   At head of title: American School of Classical Studies at Athens.   Preface to the 4th ed. signed by Oscar Broneer.   \"The Corinth Guide, originally written by Rhys Carpenter in 1928 and revised by him in 1933, was again revised by Charles H. Morgan in 1936 ... \"--Preface to the 4th ed.   ISAW copy is from the library of Paul Åström. NyNyUAW   Corinth (Greece) Antiquities.   Excavations (Archaeology) Greece Corinth.   Greece Antiquities.   Broneer, Oscar, 1894-1992.   Carpenter, Rhys, 1889-1980. Ancient Corinth, a guide to the excavations and museums.   Morgan, Charles H. (Charles Hill), 1902-1984.   American School of Classical Studies at Athens.   Åström, Paul, former owner. NyNyUAW   Åström Collection. NyNyUAW   Online version: American School of Classical Studies at Athens. Ancient Corinth. 4th ed., rev. and enl. [Athens, \"Hestia\"] 1947 (OCoLC)609019079   Z0 ZYU   GENERAL   NYU50 NISAW Small Collection DF261.C65 A57 1947 Non-circulating available Available 1 0 N 0 SMALL 0       N7KK31FMHB56YMNSV5J7KHNK3A9VV7BNF11BQA5H6LD126BJLF']\n"
     ]
    }
   ],
   "source": [
    "marcs = ['aleph-publish:003442638    00000cam a2200421 a 4500 BK 00000cam a2200421 a 4500 003442638 OCoLC 20110421131315.0 110421s1947    gr aef        000 0 eng d  (OCoLC)10220993   CIN eng CIN OCL OCLCQ OCLCG OCLCA OCLCQ NNU   eng   e-gr---   DF261.C65 A57 1947   (OCoLC)10220993   Ancient Corinth : a guide to the excavations.   Guide to the excavations of ancient Corinth   4th ed., rev. and enl.   [Athens? : Printing Office \"Hestia\"], 1947.   127 p., [2] leaves of plates : ill., plans (some fold.) ; 21 cm.   At head of title: American School of Classical Studies at Athens.   Preface to the 4th ed. signed by Oscar Broneer.   \"The Corinth Guide, originally written by Rhys Carpenter in 1928 and revised by him in 1933, was again revised by Charles H. Morgan in 1936 ... \"--Preface to the 4th ed.   ISAW copy is from the library of Paul Åström. NyNyUAW   Corinth (Greece) Antiquities.   Excavations (Archaeology) Greece Corinth.   Greece Antiquities.   Broneer, Oscar, 1894-1992.   Carpenter, Rhys, 1889-1980. Ancient Corinth, a guide to the excavations and museums.   Morgan, Charles H. (Charles Hill), 1902-1984.   American School of Classical Studies at Athens.   Åström, Paul, former owner. NyNyUAW   Åström Collection. NyNyUAW   Online version: American School of Classical Studies at Athens. Ancient Corinth. 4th ed., rev. and enl. [Athens, \"Hestia\"] 1947 (OCoLC)609019079   Z0 ZYU   GENERAL   NYU50 NISAW Small Collection DF261.C65 A57 1947 Non-circulating available Available 1 0 N 0 SMALL 0       N7KK31FMHB56YMNSV5J7KHNK3A9VV7BNF11BQA5H6LD126BJLF']\n",
    "print(marcs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Named Entity Extraction on MARC Record"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Setup Stanford NER Tagger\n",
    "# Ignore deprecation warning for now; we'll deal with it when the time comes!\n",
    "\n",
    "st = StanfordNERTagger('/usr/local/share/stanford-ner/classifiers/english.all.3class.distsim.crf.ser.gz', \n",
    "                       '/usr/local/share/stanford-ner/stanford-ner.jar',\n",
    "                       encoding='utf-8')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Functions for putting together with inside-outside-beginning (IOB) logic\n",
    "# Cf. https://stackoverflow.com/a/30666949\n",
    "#\n",
    "# For more information on IOB tagging, see https://en.wikipedia.org/wiki/Inside–outside–beginning_(tagging)\n",
    "\n",
    "def stanfordNE2BIO(tagged_sent):\n",
    "    bio_tagged_sent = []\n",
    "    prev_tag = \"O\"\n",
    "    for token, tag in tagged_sent:\n",
    "        if tag == \"O\": #O\n",
    "            bio_tagged_sent.append((token, tag))\n",
    "            prev_tag = tag\n",
    "            continue\n",
    "        if tag != \"O\" and prev_tag == \"O\": # Begin NE\n",
    "            bio_tagged_sent.append((token, \"B-\"+tag))\n",
    "            prev_tag = tag\n",
    "        elif prev_tag != \"O\" and prev_tag == tag: # Inside NE\n",
    "            bio_tagged_sent.append((token, \"I-\"+tag))\n",
    "            prev_tag = tag\n",
    "        elif prev_tag != \"O\" and prev_tag != tag: # Adjacent NE\n",
    "            bio_tagged_sent.append((token, \"B-\"+tag))\n",
    "            prev_tag = tag\n",
    "\n",
    "    return bio_tagged_sent\n",
    "\n",
    "\n",
    "def stanfordNE2tree(ne_tagged_sent):\n",
    "    bio_tagged_sent = stanfordNE2BIO(ne_tagged_sent)\n",
    "    sent_tokens, sent_ne_tags = zip(*bio_tagged_sent)\n",
    "    sent_pos_tags = [pos for token, pos in pos_tag(sent_tokens)]\n",
    "\n",
    "    sent_conlltags = [(token, pos, ne) for token, pos, ne in zip(sent_tokens, sent_pos_tags, sent_ne_tags)]\n",
    "    ne_tree = conlltags2tree(sent_conlltags)\n",
    "    return ne_tree"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 1/1 [00:04<00:00,  4.40s/it]\n"
     ]
    }
   ],
   "source": [
    "# Apply NER to each MARC record\n",
    "\n",
    "places_set = []\n",
    "\n",
    "for marc in tqdm(marcs):\n",
    "    marc_coordinates = []\n",
    "    tokenized_marc = word_tokenize(marc)\n",
    "    classified_marc = st.tag(tokenized_marc)\n",
    "    classified_marc = [item for item in classified_marc if item[0] != ''] # clean up parsing\n",
    "    ne_tree = stanfordNE2tree(classified_marc)\n",
    "\n",
    "    ne_in_sent = []\n",
    "    for subtree in ne_tree:\n",
    "        if type(subtree) == Tree: # If subtree is a noun chunk, i.e. NE != \"O\"\n",
    "            ne_label = subtree.label()\n",
    "            ne_string = \" \".join([token for token, pos in subtree.leaves()])\n",
    "            ne_in_sent.append((ne_string, ne_label))\n",
    "    \n",
    "    locations = set([tag[0] for tag in ne_in_sent if tag[1] == 'LOCATION']) # If we don't make this a set, we can use frequency info for map weight\n",
    "    \n",
    "    places_set.append(locations)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Athens', 'Corinth', 'Greece', 'Greece Antiquities', 'Greece Corinth']\n"
     ]
    }
   ],
   "source": [
    "places_set = [sorted(item) for item in places_set]\n",
    "print(places_set[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Geolocate place names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Function for querying geonames\n",
    "\n",
    "def geonames_query(location):\n",
    "    '''\n",
    "    queries geonames for given location name;\n",
    "    bounding box variables contain default values\n",
    "    based on: https://prpole.github.io/location-extraction-georeferencing/    \n",
    "    '''\n",
    "    # Todo\n",
    "    # - replace error handling\n",
    "\n",
    "    baseurl = 'http://api.geonames.org/searchJSON' #baseurl for geonames\n",
    "    username = USERNAME # Keep USERNAME in .env\n",
    "    json_decode = json.JSONDecoder() #used to parse json response\n",
    "\n",
    "    params = {\n",
    "        'username': username, \n",
    "        'name_equals': location,\n",
    "        'orderby': 'relevance',\n",
    "    }\n",
    "    \n",
    "    response = requests.get(baseurl, params=params)\n",
    "    response_string = response.text\n",
    "    parsed_response = json_decode.decode(response_string)\n",
    "    \n",
    "    if 'geonames' in parsed_response.keys():\n",
    "        if len(parsed_response['geonames']) > 0:\n",
    "            first_response = parsed_response['geonames'][0]\n",
    "            coordinates = (first_response['lat'],first_response['lng'])\n",
    "        else: \n",
    "            coordinates = ('','')\n",
    "    else:\n",
    "        coordinates = ('','')\n",
    "    return coordinates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Athens\n",
      "Corinth\n",
      "Greece\n",
      "Greece Antiquities\n",
      "Greece Corinth\n",
      "[('37.97945', '23.71622'), ('33.15401', '-97.06473'), ('43.20978', '-77.69306')]\n"
     ]
    }
   ],
   "source": [
    "# Build list of likely coordinates for places\n",
    "\n",
    "places_list = []\n",
    "coordinates_list = []\n",
    "\n",
    "for places in places_set[:1]:\n",
    "    coordinates = []\n",
    "    for place in places:\n",
    "        print(place)\n",
    "        ll = geonames_query(place)\n",
    "        if ll != ('',''):\n",
    "            places_list.append(place)\n",
    "            coordinates.append(ll)\n",
    "    coordinates_list.append(coordinates)    \n",
    "\n",
    "print(coordinates_list[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Convert coordinates to float\n",
    "\n",
    "coordinates_list = [[(float(lat), float(long)) for lat, long in item] for item in coordinates_list]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Athens', 'Corinth', 'Greece']\n",
      "[(37.97945, 23.71622), (33.15401, -97.06473), (43.20978, -77.69306)]\n"
     ]
    }
   ],
   "source": [
    "# Get sample\n",
    "\n",
    "print(places_list)\n",
    "print(coordinates_list[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create map"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfYjA2ZTc0Yjk4OWFlNDMwZjgyNmZlYmQ5MGJiMGMwYjkgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogOTYwLjBweDsKICAgICAgICAgICAgICAgIGhlaWdodDogNTEyLjBweDsKICAgICAgICAgICAgICAgIGxlZnQ6IDAuMCU7CiAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfYjA2ZTc0Yjk4OWFlNDMwZjgyNmZlYmQ5MGJiMGMwYjkiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgICAgICAgICAgCgogICAgICAgICAgICB2YXIgbWFwX2IwNmU3NGI5ODlhZTQzMGY4MjZmZWJkOTBiYjBjMGI5ID0gTC5tYXAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbWFwX2IwNmU3NGI5ODlhZTQzMGY4MjZmZWJkOTBiYjBjMGI5JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtjZW50ZXI6IFszNy45Nzk0NSwyMy43MTYyMl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b29tOiA0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4Qm91bmRzOiBib3VuZHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXllcnM6IFtdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGRDb3B5SnVtcDogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl85NGIxMDgyYWQzMGE0ODY0ODkyYmFmOGU3YjVjZTkzNSA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgJ2h0dHBzOi8vY2FydG9kYi1iYXNlbWFwcy17c30uZ2xvYmFsLnNzbC5mYXN0bHkubmV0L2xpZ2h0X2FsbC97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2IwNmU3NGI5ODlhZTQzMGY4MjZmZWJkOTBiYjBjMGI5KTsKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9mZTgzZjliNGY5M2M0Mzg3OGZjYzdkYjBlMjdjOGUyOCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM3Ljk3OTQ1LDIzLjcxNjIyXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfYjA2ZTc0Yjk4OWFlNDMwZjgyNmZlYmQ5MGJiMGMwYjkpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMGM1OGQzOTA4OGEzNDIyMDk0YzU0YmIyZDIyMzYxNzIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2UxZDc2M2IyOGQwNDdkNDgzNjA1NTIxYTg2MjAyYTMgPSAkKCc8ZGl2IGlkPSJodG1sXzNlMWQ3NjNiMjhkMDQ3ZDQ4MzYwNTUyMWE4NjIwMmEzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BdGhlbnMgMzcuOTc5NDUyMy43MTYyMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGM1OGQzOTA4OGEzNDIyMDk0YzU0YmIyZDIyMzYxNzIuc2V0Q29udGVudChodG1sXzNlMWQ3NjNiMjhkMDQ3ZDQ4MzYwNTUyMWE4NjIwMmEzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfZmU4M2Y5YjRmOTNjNDM4NzhmY2M3ZGIwZTI3YzhlMjguYmluZFBvcHVwKHBvcHVwXzBjNThkMzkwODhhMzQyMjA5NGM1NGJiMmQyMjM2MTcyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzNhYjRlN2E3NzIzNTRlOTM4MTAxY2Y2NTQ3MzIxMDY1ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzMuMTU0MDEsLTk3LjA2NDczXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfYjA2ZTc0Yjk4OWFlNDMwZjgyNmZlYmQ5MGJiMGMwYjkpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDJhZmZhYzljMThiNGE5ZGJiNmFjY2FiOTNhZmJmNjAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWY2MTBiOThhNmM1NDIzMDgwZGY1YWRlMWFmZDYwZjkgPSAkKCc8ZGl2IGlkPSJodG1sXzFmNjEwYjk4YTZjNTQyMzA4MGRmNWFkZTFhZmQ2MGY5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Db3JpbnRoIDMzLjE1NDAxLTk3LjA2NDczPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80MmFmZmFjOWMxOGI0YTlkYmI2YWNjYWI5M2FmYmY2MC5zZXRDb250ZW50KGh0bWxfMWY2MTBiOThhNmM1NDIzMDgwZGY1YWRlMWFmZDYwZjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl8zYWI0ZTdhNzcyMzU0ZTkzODEwMWNmNjU0NzMyMTA2NS5iaW5kUG9wdXAocG9wdXBfNDJhZmZhYzljMThiNGE5ZGJiNmFjY2FiOTNhZmJmNjApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfYzhiY2E1MWJiMGVmNGFkMTgyNTVmMTM1NjhmNmE2YjkgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFs0My4yMDk3OCwtNzcuNjkzMDZdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF9iMDZlNzRiOTg5YWU0MzBmODI2ZmViZDkwYmIwYzBiOSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mZGQzMzEyNTk4NmQ0OGI1YTgxOTU1ZWQ4YzQyNGY2ZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80NTE0MTBkYTNjOGY0YTc3YjcxOGFkNjBjMTNhNDI3NyA9ICQoJzxkaXYgaWQ9Imh0bWxfNDUxNDEwZGEzYzhmNGE3N2I3MThhZDYwYzEzYTQyNzciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdyZWVjZSA0My4yMDk3OC03Ny42OTMwNjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmRkMzMxMjU5ODZkNDhiNWE4MTk1NWVkOGM0MjRmNmUuc2V0Q29udGVudChodG1sXzQ1MTQxMGRhM2M4ZjRhNzdiNzE4YWQ2MGMxM2E0Mjc3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfYzhiY2E1MWJiMGVmNGFkMTgyNTVmMTM1NjhmNmE2YjkuYmluZFBvcHVwKHBvcHVwX2ZkZDMzMTI1OTg2ZDQ4YjVhODE5NTVlZDhjNDI0ZjZlKTsKCiAgICAgICAgICAgIAogICAgICAgIAo8L3NjcmlwdD4=\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x1146ae358>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Set up Folium and populate with coordinates\n",
    "\n",
    "basemap = folium.Map(location=[37.97945, 23.71622], zoom_start=4, tiles='cartodbpositron', width=960, height=512)\n",
    "\n",
    "for i, c in enumerate(coordinates_list[0]):\n",
    "    folium.Marker([c[0], c[1]], popup='{} {}{}'.format(places_list[i], c[0], c[1])).add_to(basemap)\n",
    "    \n",
    "basemap"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfYjA2ZTc0Yjk4OWFlNDMwZjgyNmZlYmQ5MGJiMGMwYjkgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogOTYwLjBweDsKICAgICAgICAgICAgICAgIGhlaWdodDogNTEyLjBweDsKICAgICAgICAgICAgICAgIGxlZnQ6IDAuMCU7CiAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfYjA2ZTc0Yjk4OWFlNDMwZjgyNmZlYmQ5MGJiMGMwYjkiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgICAgICAgICAgCgogICAgICAgICAgICB2YXIgbWFwX2IwNmU3NGI5ODlhZTQzMGY4MjZmZWJkOTBiYjBjMGI5ID0gTC5tYXAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbWFwX2IwNmU3NGI5ODlhZTQzMGY4MjZmZWJkOTBiYjBjMGI5JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtjZW50ZXI6IFszNy45Nzk0NSwyMy43MTYyMl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b29tOiAyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4Qm91bmRzOiBib3VuZHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXllcnM6IFtdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGRDb3B5SnVtcDogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl85NGIxMDgyYWQzMGE0ODY0ODkyYmFmOGU3YjVjZTkzNSA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgJ2h0dHBzOi8vY2FydG9kYi1iYXNlbWFwcy17c30uZ2xvYmFsLnNzbC5mYXN0bHkubmV0L2xpZ2h0X2FsbC97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2IwNmU3NGI5ODlhZTQzMGY4MjZmZWJkOTBiYjBjMGI5KTsKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9mZTgzZjliNGY5M2M0Mzg3OGZjYzdkYjBlMjdjOGUyOCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM3Ljk3OTQ1LDIzLjcxNjIyXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfYjA2ZTc0Yjk4OWFlNDMwZjgyNmZlYmQ5MGJiMGMwYjkpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMGM1OGQzOTA4OGEzNDIyMDk0YzU0YmIyZDIyMzYxNzIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2UxZDc2M2IyOGQwNDdkNDgzNjA1NTIxYTg2MjAyYTMgPSAkKCc8ZGl2IGlkPSJodG1sXzNlMWQ3NjNiMjhkMDQ3ZDQ4MzYwNTUyMWE4NjIwMmEzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BdGhlbnMgMzcuOTc5NDUyMy43MTYyMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGM1OGQzOTA4OGEzNDIyMDk0YzU0YmIyZDIyMzYxNzIuc2V0Q29udGVudChodG1sXzNlMWQ3NjNiMjhkMDQ3ZDQ4MzYwNTUyMWE4NjIwMmEzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfZmU4M2Y5YjRmOTNjNDM4NzhmY2M3ZGIwZTI3YzhlMjguYmluZFBvcHVwKHBvcHVwXzBjNThkMzkwODhhMzQyMjA5NGM1NGJiMmQyMjM2MTcyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzNhYjRlN2E3NzIzNTRlOTM4MTAxY2Y2NTQ3MzIxMDY1ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzMuMTU0MDEsLTk3LjA2NDczXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfYjA2ZTc0Yjk4OWFlNDMwZjgyNmZlYmQ5MGJiMGMwYjkpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDJhZmZhYzljMThiNGE5ZGJiNmFjY2FiOTNhZmJmNjAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWY2MTBiOThhNmM1NDIzMDgwZGY1YWRlMWFmZDYwZjkgPSAkKCc8ZGl2IGlkPSJodG1sXzFmNjEwYjk4YTZjNTQyMzA4MGRmNWFkZTFhZmQ2MGY5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Db3JpbnRoIDMzLjE1NDAxLTk3LjA2NDczPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80MmFmZmFjOWMxOGI0YTlkYmI2YWNjYWI5M2FmYmY2MC5zZXRDb250ZW50KGh0bWxfMWY2MTBiOThhNmM1NDIzMDgwZGY1YWRlMWFmZDYwZjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl8zYWI0ZTdhNzcyMzU0ZTkzODEwMWNmNjU0NzMyMTA2NS5iaW5kUG9wdXAocG9wdXBfNDJhZmZhYzljMThiNGE5ZGJiNmFjY2FiOTNhZmJmNjApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfYzhiY2E1MWJiMGVmNGFkMTgyNTVmMTM1NjhmNmE2YjkgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFs0My4yMDk3OCwtNzcuNjkzMDZdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF9iMDZlNzRiOTg5YWU0MzBmODI2ZmViZDkwYmIwYzBiOSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mZGQzMzEyNTk4NmQ0OGI1YTgxOTU1ZWQ4YzQyNGY2ZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80NTE0MTBkYTNjOGY0YTc3YjcxOGFkNjBjMTNhNDI3NyA9ICQoJzxkaXYgaWQ9Imh0bWxfNDUxNDEwZGEzYzhmNGE3N2I3MThhZDYwYzEzYTQyNzciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdyZWVjZSA0My4yMDk3OC03Ny42OTMwNjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmRkMzMxMjU5ODZkNDhiNWE4MTk1NWVkOGM0MjRmNmUuc2V0Q29udGVudChodG1sXzQ1MTQxMGRhM2M4ZjRhNzdiNzE4YWQ2MGMxM2E0Mjc3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfYzhiY2E1MWJiMGVmNGFkMTgyNTVmMTM1NjhmNmE2YjkuYmluZFBvcHVwKHBvcHVwX2ZkZDMzMTI1OTg2ZDQ4YjVhODE5NTVlZDhjNDI0ZjZlKTsKCiAgICAgICAgICAgIAogICAgICAgIAo8L3NjcmlwdD4=\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x1146ae358>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Why does only Athens return a result on the map? Check zoom...\n",
    "\n",
    "basemap.zoom_start = 2\n",
    "basemap"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Disambiguate placenames"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# So we have learned that we can't use the top 'relevance' score from the Geoname API, or we\n",
    "# get results like 'Corinth, Texas' and 'Greece, NY'. We need some plan for disambiguating the\n",
    "# Geonames results..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "import geocoder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Athens', 'Corinth', 'Greece']"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "places_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'address': 'Corinth',\n",
      " 'class_description': 'country, state, region,...',\n",
      " 'code': 'ADM2',\n",
      " 'country': 'Saint Lucia',\n",
      " 'country_code': 'LC',\n",
      " 'description': 'second-order administrative division',\n",
      " 'feature_class': 'A',\n",
      " 'geonames_id': 11351423,\n",
      " 'lat': '14.0471',\n",
      " 'lng': '-60.96046',\n",
      " 'ok': True,\n",
      " 'population': 1382,\n",
      " 'raw': {'adminCode1': '06',\n",
      "         'adminCodes1': {'ISO3166_2': '06'},\n",
      "         'adminName1': 'Gros-Islet',\n",
      "         'countryCode': 'LC',\n",
      "         'countryId': '3576468',\n",
      "         'countryName': 'Saint Lucia',\n",
      "         'fcl': 'A',\n",
      "         'fclName': 'country, state, region,...',\n",
      "         'fcode': 'ADM2',\n",
      "         'fcodeName': 'second-order administrative division',\n",
      "         'geonameId': 11351423,\n",
      "         'lat': '14.0471',\n",
      "         'lng': '-60.96046',\n",
      "         'name': 'Corinth',\n",
      "         'population': 1382,\n",
      "         'toponymName': 'Corinth'},\n",
      " 'state': 'Gros-Islet',\n",
      " 'state_code': '06',\n",
      " 'status': 'OK'}\n"
     ]
    }
   ],
   "source": [
    "# Retrieve json from geonames API (for fun this time using geocoder)\n",
    "\n",
    "geocoder_results = []\n",
    "\n",
    "for place in places_list:\n",
    "    results = geocoder.geonames(place, maxRows=10, key=USERNAME)\n",
    "    jsons = []\n",
    "    for result in results:\n",
    "        jsons.append(result.json)\n",
    "    geocoder_results.append(jsons)\n",
    "    \n",
    "pprint(geocoder_results[1][0]) # Corinth, but a wrong Corinth"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('Athens', 37.97945, 23.71622), ('Athens', 39.32924, -82.10126), ('Athens', 33.96095, -83.37794), ('Athens', 39.33386, -82.04513), ('Athens Airport', 37.93636, 23.94447), ('The Plains', 39.36896, -82.13237), ('Athens', 13.90574, -60.89184), ('Strouds Run State Park', 39.34924, -82.03236), ('Glouster', 39.50313, -82.08459), ('Hockingport', 39.18813, -81.7518), ('Corinth', 14.0471, -60.96046), ('Corinth Estate', 14.04336, -60.95388), ('Corinth', 37.94007, 22.9513), ('Corinth Head', -53.0, 73.41667), ('Corinth/La Bel Lair', 14.04469, -60.94484), ('Corinth', 37.8144, 22.94352), ('Achaea (Roman province)', 37.93445, 22.92615), ('Ancient Corinth', 37.90953, 22.88353), ('Corinth', 34.93425, -88.52227), ('Sofiko', 37.79412, 23.05204), ('Greece', 39.0, 22.0), ('Pátrai', 38.24444, 21.73444), ('Central Greece', 38.35243, 23.13995), ('West Greece', 38.48799, 21.2915), ('Central Greece and Euboea', 38.66667, 22.5), ('Lamia', 38.9, 22.43333), ('Achaea', 38.13333, 22.0), ('Thebes', 38.325, 23.31889), ('Euboea Island', 38.5, 24.0), ('Boeotia', 38.33333, 23.25)]\n"
     ]
    }
   ],
   "source": [
    "# Iterate over geocoder_results and keep all lat/long\n",
    "\n",
    "coordinates = []\n",
    "\n",
    "for i, results in enumerate(geocoder_results):\n",
    "    for item in results:\n",
    "        if item['lat'] and item['lng']:\n",
    "            coordinates.append((item['address'], float(item['lat']), float(item['lng'])))\n",
    "\n",
    "print(coordinates)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create revised map"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Still not what we are looking for, but the 'cluster' premise gives us a reason to believe that one subset of coordinates, i.e. the one near Greece, are a better fit that the others."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Still not what we are looking for...\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogOTYwLjBweDsKICAgICAgICAgICAgICAgIGhlaWdodDogNTEyLjBweDsKICAgICAgICAgICAgICAgIGxlZnQ6IDAuMCU7CiAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgICAgICAgICAgCgogICAgICAgICAgICB2YXIgbWFwXzhhNGYzMWEyMjI4ODQ5ODg5ZjhiNGRlNTIyZjRiMGM5ID0gTC5tYXAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbWFwXzhhNGYzMWEyMjI4ODQ5ODg5ZjhiNGRlNTIyZjRiMGM5JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtjZW50ZXI6IFszMCwwXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHpvb206IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyczogW10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZENvcHlKdW1wOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyX2Q3NmQxZDdkMDZlNDQ4MzU4ZTI3MTU2NTNjMzc3NDM2ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAnaHR0cHM6Ly9jYXJ0b2RiLWJhc2VtYXBzLXtzfS5nbG9iYWwuc3NsLmZhc3RseS5uZXQvbGlnaHRfYWxsL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgICAgICAgICB7CiAgImF0dHJpYnV0aW9uIjogbnVsbCwKICAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsCiAgIm1heFpvb20iOiAxOCwKICAibWluWm9vbSI6IDEsCiAgIm5vV3JhcCI6IGZhbHNlLAogICJzdWJkb21haW5zIjogImFiYyIKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzFmMWIzNGQ3YWNmNjQ4ZWI5MTc1NDE4YjIyOWI2ODI1ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzcuOTc5NDUsMjMuNzE2MjJdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84YTRmMzFhMjIyODg0OTg4OWY4YjRkZTUyMmY0YjBjOSk7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzMxZDZjNGQ3YjYzZjRmZTU4NjBiZWQ5MzAyN2JiNWI1ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzkuMzI5MjQsLTgyLjEwMTI2XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl82MjhlNmNlNDY4ZTk0YzgyOTNlMGEyN2ZlNWE4ODQ0MCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzMzLjk2MDk1LC04My4zNzc5NF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzhhNGYzMWEyMjI4ODQ5ODg5ZjhiNGRlNTIyZjRiMGM5KTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfN2Q4ZmU0Mjg0MzRiNGFhZjg2ZDZlZGEzZWJkODg3NGUgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszOS4zMzM4NiwtODIuMDQ1MTNdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84YTRmMzFhMjIyODg0OTg4OWY4YjRkZTUyMmY0YjBjOSk7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzY0ZjMwNzkwNDExZDQzZWM5YmI3NmJhMzliYmM5YjhlID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzcuOTM2MzYsMjMuOTQ0NDddLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84YTRmMzFhMjIyODg0OTg4OWY4YjRkZTUyMmY0YjBjOSk7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2MwNGNjYzA2ZDE0NTRlNjBhNDM5OGMyMmRjNDc1NmUyID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzkuMzY4OTYsLTgyLjEzMjM3XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9mYjdjNjA3ZDk0ZDQ0ZjJhODMwM2YwN2I3NzY1YWMxYiA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzEzLjkwNTc0LC02MC44OTE4NF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzhhNGYzMWEyMjI4ODQ5ODg5ZjhiNGRlNTIyZjRiMGM5KTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfOWNmODYwZTU1YTM3NDg5OTgyYzk5ZWYxNzg5Y2Q3YTQgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszOS4zNDkyNCwtODIuMDMyMzZdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84YTRmMzFhMjIyODg0OTg4OWY4YjRkZTUyMmY0YjBjOSk7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2RhMWZjODExZWNmYTRmMDlhZTUyMGI5MmMxM2QyN2NhID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzkuNTAzMTMsLTgyLjA4NDU5XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl85MzIxNWYxMThhZTA0MTBjYTUxN2E5NTQ1ODY1OTFjMyA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM5LjE4ODEzLC04MS43NTE4XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl84NDRhYjZiZjNhNjE0NDZhYjRiNjVkYmI0YTg4Njc4YyA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzE0LjA0NzEsLTYwLjk2MDQ2XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9hZDNjOTk2ZWE0YTM0MTYwODVhZTlkMjhhNGI3MzE3MSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzE0LjA0MzM2LC02MC45NTM4OF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzhhNGYzMWEyMjI4ODQ5ODg5ZjhiNGRlNTIyZjRiMGM5KTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfODNlY2Q4MzIyZjhlNGRjMGI1YmQ5ZjkwNGYyMThjYjkgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNy45NDAwNywyMi45NTEzXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl8wYjBiMjY0MjU1MWQ0NzM2YjZhODljNWI2YTI2ZDJkZSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWy01My4wLDczLjQxNjY3XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl84MzQ5NDAyN2Q3YTc0NWViODE0ZTgyYzBhNmI4OTk2MyA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzE0LjA0NDY5LC02MC45NDQ4NF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzhhNGYzMWEyMjI4ODQ5ODg5ZjhiNGRlNTIyZjRiMGM5KTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfYWRlNDkzMDhjYWNiNDZiMmI0MTZmZTIwODIyOTBjOTYgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNy44MTQ0LDIyLjk0MzUyXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl81YzY1MjRiNDIxMDQ0MzUyYTlmNzliMjkzMDhjYWFhOSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM3LjkzNDQ1LDIyLjkyNjE1XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl82NjEzZGJhZGVjOWY0NzllYWQ1MGFmOTQxNzYxMWZmMiA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM3LjkwOTUzLDIyLjg4MzUzXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9jZDE0N2ViZTAxOTc0MDg2YjllZDIwNmRjZWZjNGUzMiA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM0LjkzNDI1LC04OC41MjIyN10sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzhhNGYzMWEyMjI4ODQ5ODg5ZjhiNGRlNTIyZjRiMGM5KTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfYTc1Nzg5ZjRhZjIyNDcxNDgxMGEwNDU5Mjc1MjhjY2IgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNy43OTQxMiwyMy4wNTIwNF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzhhNGYzMWEyMjI4ODQ5ODg5ZjhiNGRlNTIyZjRiMGM5KTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfYThmMTViMmRiZDg5NGJkMzk2NmI4ZWQ1YmIzOTA1OTEgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszOS4wLDIyLjBdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84YTRmMzFhMjIyODg0OTg4OWY4YjRkZTUyMmY0YjBjOSk7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzc5MzI1MjdkMjM2MzRhYjFiN2UwYTkzY2FhMmUyYjIxID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzguMjQ0NDQsMjEuNzM0NDRdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84YTRmMzFhMjIyODg0OTg4OWY4YjRkZTUyMmY0YjBjOSk7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2YzZTNhOWQ0ZWU1MTRlNDBhZDZkODljMjVhZDk2ZmQzID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzguMzUyNDMsMjMuMTM5OTVdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84YTRmMzFhMjIyODg0OTg4OWY4YjRkZTUyMmY0YjBjOSk7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2M5OTJmMmNmYjBlNDQ1NThiZDhiNGNhNmI0NDdmYjliID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzguNDg3OTksMjEuMjkxNV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzhhNGYzMWEyMjI4ODQ5ODg5ZjhiNGRlNTIyZjRiMGM5KTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfYjYwOWYxYWYzY2E0NDVhMzgxMTFjODJiZDE3Yzk3M2QgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszOC42NjY2NywyMi41XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl82ZDQ5NDE2YTQ0MGU0NDQzOTkzOWQ2MWE2ZDI4NDZlZiA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM4LjksMjIuNDMzMzNdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84YTRmMzFhMjIyODg0OTg4OWY4YjRkZTUyMmY0YjBjOSk7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzdhMWRlMDc0MjQ0NTRhYTFhMWQ4ZDIxODUwOTJkY2YxID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzguMTMzMzMsMjIuMF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzhhNGYzMWEyMjI4ODQ5ODg5ZjhiNGRlNTIyZjRiMGM5KTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfY2E5OGY4ZmFkNWE2NDQ2ZTg3M2UyYjFjYjU1NTM1NjQgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszOC4zMjUsMjMuMzE4ODldLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84YTRmMzFhMjIyODg0OTg4OWY4YjRkZTUyMmY0YjBjOSk7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzM3YzYzOWMzOWJjMTQxZmZhYjhkN2JlMWNhNWIyNWJmID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzguNSwyNC4wXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl85NTVhNWY5OTExYzI0Mjc0OWVmMjhmNWJiMDE0NWU1ZSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM4LjMzMzMzLDIzLjI1XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfOGE0ZjMxYTIyMjg4NDk4ODlmOGI0ZGU1MjJmNGIwYzkpOwogICAgICAgICAgICAKPC9zY3JpcHQ+\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x11619dda0>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Set up Folium and populate with all coordinates\n",
    "\n",
    "basemap = folium.Map(location=[30, 0], zoom_start=2, tiles='cartodbpositron', width=960, height=512)\n",
    "\n",
    "for i, c in enumerate(coordinates):\n",
    "    folium.Marker([c[1], c[2]]).add_to(basemap)\n",
    "\n",
    "print('Still not what we are looking for...')\n",
    "basemap"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cluster the coordinates with DBSCAN"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Following this [notebook](https://github.com/gboeing/2014-summer-travels/blob/master/clustering-scikitlearn.ipynb) by Geoff Boeing for geographical clustering with DBScan"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd, numpy as np, matplotlib.pyplot as plt, time\n",
    "from sklearn.cluster import DBSCAN\n",
    "from sklearn import metrics\n",
    "from geopy.distance import great_circle\n",
    "from shapely.geometry import MultiPoint\n",
    "%matplotlib inline\n",
    "\n",
    "# define the number of kilometers in one radian\n",
    "kms_per_radian = 6371.0088"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>placename</th>\n",
       "      <th>lat</th>\n",
       "      <th>lon</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Athens</td>\n",
       "      <td>37.97945</td>\n",
       "      <td>23.71622</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Athens</td>\n",
       "      <td>39.32924</td>\n",
       "      <td>-82.10126</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Athens</td>\n",
       "      <td>33.96095</td>\n",
       "      <td>-83.37794</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Athens</td>\n",
       "      <td>39.33386</td>\n",
       "      <td>-82.04513</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Athens Airport</td>\n",
       "      <td>37.93636</td>\n",
       "      <td>23.94447</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        placename       lat       lon\n",
       "0          Athens  37.97945  23.71622\n",
       "1          Athens  39.32924 -82.10126\n",
       "2          Athens  33.96095 -83.37794\n",
       "3          Athens  39.33386 -82.04513\n",
       "4  Athens Airport  37.93636  23.94447"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# make dataframe\n",
    "\n",
    "df = pd.DataFrame.from_records(coordinates, columns=['placename', 'lat', 'lon'])\n",
    "df[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/pbartleby/.local/share/virtualenvs/mapping-experiments-GK9mgOWS/lib/python3.6/site-packages/ipykernel_launcher.py:2: FutureWarning: Method .as_matrix will be removed in a future version. Use .values instead.\n",
      "  \n"
     ]
    }
   ],
   "source": [
    "# represent points consistently as (lat, lon)\n",
    "coords = df.as_matrix(columns=['lat', 'lon'])\n",
    "\n",
    "# define epsilon as 1.5 kilometers, converted to radians for use by haversine\n",
    "epsilon = 1000 / kms_per_radian"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clustered 30 points down to 4 clusters, for 86.7% compression in 0.00 seconds\n",
      "Silhouette coefficient: 0.934\n"
     ]
    }
   ],
   "source": [
    "# run the clustering algorithm\n",
    "\n",
    "start_time = time.time()\n",
    "db = DBSCAN(eps=epsilon, min_samples=1, algorithm='ball_tree', metric='haversine').fit(np.radians(coords))\n",
    "cluster_labels = db.labels_\n",
    "\n",
    "# get the number of clusters\n",
    "num_clusters = len(set(cluster_labels))\n",
    "\n",
    "# all done, print the outcome\n",
    "message = 'Clustered {:,} points down to {:,} clusters, for {:.1f}% compression in {:,.2f} seconds'\n",
    "print(message.format(len(df), num_clusters, 100*(1 - float(num_clusters) / len(df)), time.time()-start_time))\n",
    "print('Silhouette coefficient: {:0.03f}'.format(metrics.silhouette_score(coords, cluster_labels)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0    [[37.97945, 23.71622], [37.93636, 23.94447], [...\n",
      "1    [[39.32924, -82.10126], [33.96095, -83.37794],...\n",
      "2    [[13.90574, -60.89184], [14.0471, -60.96046], ...\n",
      "3                                  [[-53.0, 73.41667]]\n",
      "dtype: object\n"
     ]
    }
   ],
   "source": [
    "# turn the clusters in to a pandas series, where each element is a cluster of points\n",
    "\n",
    "clusters = pd.Series([coords[cluster_labels==n] for n in range(num_clusters)])\n",
    "print(clusters)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "# get centers\n",
    "\n",
    "def get_centermost_point(cluster):\n",
    "    centroid = (MultiPoint(cluster).centroid.x, MultiPoint(cluster).centroid.y)\n",
    "    centermost_point = min(cluster, key=lambda point: great_circle(point, centroid).m)\n",
    "    return tuple(centermost_point)\n",
    "\n",
    "centermost_points = clusters.map(get_centermost_point)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cluster 0 centered at (38.35243, 23.13995) contains 17 points.\n",
      "Cluster 1 centered at (39.32924, -82.10126) contains 8 points.\n",
      "Cluster 2 centered at (14.04469, -60.94484) contains 4 points.\n",
      "Cluster 3 centered at (-53.0, 73.41667) contains 1 points.\n"
     ]
    }
   ],
   "source": [
    "# summarize clusters\n",
    "\n",
    "max_cluster_index = 0\n",
    "max_temp = 0\n",
    "\n",
    "for i, cluster in enumerate(clusters):\n",
    "    print(f'Cluster {i} centered at {centermost_points[i]} contains {len(cluster)} points.')\n",
    "    if len(cluster) > max_temp:\n",
    "        max_temp = len(cluster)\n",
    "        max_cluster_index = i"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "# keep only largest cluster\n",
    "\n",
    "main_cluster = clusters[max_cluster_index]\n",
    "main_center = centermost_points[max_cluster_index]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "# convert main_cluster coordinates from numpy array to tuple of floats\n",
    "\n",
    "main_cluster_coordinates = tuple(map(tuple, main_cluster))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "All points in largest cluster...\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfMzAwNjhjNTYyMTdlNDEzY2E2OTAyZTIzNjgwNDE4NmIgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogOTYwLjBweDsKICAgICAgICAgICAgICAgIGhlaWdodDogNTEyLjBweDsKICAgICAgICAgICAgICAgIGxlZnQ6IDAuMCU7CiAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfMzAwNjhjNTYyMTdlNDEzY2E2OTAyZTIzNjgwNDE4NmIiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgICAgICAgICAgCgogICAgICAgICAgICB2YXIgbWFwXzMwMDY4YzU2MjE3ZTQxM2NhNjkwMmUyMzY4MDQxODZiID0gTC5tYXAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbWFwXzMwMDY4YzU2MjE3ZTQxM2NhNjkwMmUyMzY4MDQxODZiJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtjZW50ZXI6IFszOC4zNTI0MywyMy4xMzk5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b29tOiA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4Qm91bmRzOiBib3VuZHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXllcnM6IFtdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGRDb3B5SnVtcDogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl80MTM0NWNlZDM5NzY0NzY3YWZkNTBlZTZmNDFkNzY4NCA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgJ2h0dHBzOi8vY2FydG9kYi1iYXNlbWFwcy17c30uZ2xvYmFsLnNzbC5mYXN0bHkubmV0L2xpZ2h0X2FsbC97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzMwMDY4YzU2MjE3ZTQxM2NhNjkwMmUyMzY4MDQxODZiKTsKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl8xOGE2ZWE5YzIwZjY0MGJjODg4MzI4MWE3Y2YyMmNhZCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM3Ljk3OTQ1LDIzLjcxNjIyXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfMzAwNjhjNTYyMTdlNDEzY2E2OTAyZTIzNjgwNDE4NmIpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9iYWVkYjJiY2EwN2U0M2I5YWY4YTYwYmVlY2RiOTRjNyA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM3LjkzNjM2LDIzLjk0NDQ3XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfMzAwNjhjNTYyMTdlNDEzY2E2OTAyZTIzNjgwNDE4NmIpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9jYzg3NjY2NmFlNTA0YmI4YjgwNzllZWFjNmMyMTllMCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM3Ljk0MDA3LDIyLjk1MTNdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF8zMDA2OGM1NjIxN2U0MTNjYTY5MDJlMjM2ODA0MTg2Yik7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2NmZWY5ZmU0ODU1ODRhNTJiYTk1NWUxYWJmMGNhYmFkID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzcuODE0NCwyMi45NDM1Ml0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzMwMDY4YzU2MjE3ZTQxM2NhNjkwMmUyMzY4MDQxODZiKTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfYWViMTU3YjI5NmI4NGUxMGFiNzM0YWIxMmY1OTllMDMgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNy45MzQ0NSwyMi45MjYxNV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzMwMDY4YzU2MjE3ZTQxM2NhNjkwMmUyMzY4MDQxODZiKTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfZmE5Y2Y4Y2I3ZTc0NDQ1ZmI4YWRkNDQ0ZjI4NDkxZjAgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNy45MDk1MywyMi44ODM1M10sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzMwMDY4YzU2MjE3ZTQxM2NhNjkwMmUyMzY4MDQxODZiKTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfZDhhNmU4NjA0YmIwNDYwMThhZTkyNzIwMGQ2NmFlODEgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNy43OTQxMiwyMy4wNTIwNF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzMwMDY4YzU2MjE3ZTQxM2NhNjkwMmUyMzY4MDQxODZiKTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfMjY2MDc5NDY3MDYzNGJiZTkyZjE2NTBhODhjYjliNWEgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszOS4wLDIyLjBdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF8zMDA2OGM1NjIxN2U0MTNjYTY5MDJlMjM2ODA0MTg2Yik7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2JlMzFjYjNmZDY3YjQ0N2E4NDMwZjI5NWRlMTI1NWM3ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzguMjQ0NDQsMjEuNzM0NDRdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF8zMDA2OGM1NjIxN2U0MTNjYTY5MDJlMjM2ODA0MTg2Yik7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzMzNGMyOWEzNTg3NTQyN2JhZDI3ZjYxZGZmNDFjZWI0ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzguMzUyNDMsMjMuMTM5OTVdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF8zMDA2OGM1NjIxN2U0MTNjYTY5MDJlMjM2ODA0MTg2Yik7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzM5MzUwMzdkZjZlNDRkMjViOTJlMzY0NzBmYTNiZTRlID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzguNDg3OTksMjEuMjkxNV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzMwMDY4YzU2MjE3ZTQxM2NhNjkwMmUyMzY4MDQxODZiKTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfYjM2YzY1NGQxMzBkNDM4NDg2NTY3ZTYwY2FiZmEwODggPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszOC42NjY2NywyMi41XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfMzAwNjhjNTYyMTdlNDEzY2E2OTAyZTIzNjgwNDE4NmIpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9jY2FkNDUzOGEwMjY0ZTk2YTI2OGU5OGY4NTNlNTAxNyA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM4LjksMjIuNDMzMzNdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF8zMDA2OGM1NjIxN2U0MTNjYTY5MDJlMjM2ODA0MTg2Yik7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2M3NDQzZGE5Y2Q3ZDRmMWU5YTVkODhmOTYzZjlkYTM3ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzguMTMzMzMsMjIuMF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzMwMDY4YzU2MjE3ZTQxM2NhNjkwMmUyMzY4MDQxODZiKTsKICAgICAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfMGFlZDhjOTZlY2Q2NDEwMGE2NWM4OTI1MzBlOTQ0MTUgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszOC4zMjUsMjMuMzE4ODldLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF8zMDA2OGM1NjIxN2U0MTNjYTY5MDJlMjM2ODA0MTg2Yik7CiAgICAgICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2VlOGY2ZDYwODllMjQyZWQ4MWJiNGM2YjdkMTBiYTc2ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzguNSwyNC4wXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfMzAwNjhjNTYyMTdlNDEzY2E2OTAyZTIzNjgwNDE4NmIpOwogICAgICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl85MmRmMDA5OWNmY2I0MzU1YmEwNWU2ZWE5ZjY0YmQyMCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM4LjMzMzMzLDIzLjI1XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfMzAwNjhjNTYyMTdlNDEzY2E2OTAyZTIzNjgwNDE4NmIpOwogICAgICAgICAgICAKPC9zY3JpcHQ+\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x117d5f2e8>"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# make new map\n",
    "\n",
    "basemap = folium.Map(location=main_center, zoom_start=6, tiles='cartodbpositron', width=960, height=512)\n",
    "\n",
    "for i, c in enumerate(main_cluster_coordinates):\n",
    "    folium.Marker([c[0], c[1]]).add_to(basemap)\n",
    "\n",
    "print(\"All points in largest cluster...\")\n",
    "basemap"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "# define functions to compute distance from center following https://stackoverflow.com/a/41337005\n",
    "\n",
    "from math import cos, asin, sqrt\n",
    "\n",
    "def distance(lat1, lon1, lat2, lon2):\n",
    "    p = 0.017453292519943295\n",
    "    a = 0.5 - cos((lat2-lat1)*p)/2 + cos(lat1*p)*cos(lat2*p) * (1-cos((lon2-lon1)*p)) / 2\n",
    "    return 12742 * asin(sqrt(a))\n",
    "\n",
    "def closest(data, v):\n",
    "    return min(data, key=lambda p: distance(v[0],v[1],p[0],p[1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "# iterate over results and find closest distance from main cluster center\n",
    "\n",
    "top_places = []\n",
    "top_coordinates = []\n",
    "\n",
    "for results in geocoder_results:\n",
    "\n",
    "    coords_ = []\n",
    "    for result in results:\n",
    "        coords_.append((float(result['lat']), float(result['lng'])))\n",
    "    closest_coordinates = closest(coords_, main_center)\n",
    "    top_places.append(next(item['address'] for item in results if float(item['lat']) == closest_coordinates[0]))\n",
    "    top_coordinates.append(closest_coordinates)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Map of relevant locations in Broneer et al.'s \"Ancient Corinth: A guide to the excavations\"\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfNTc5MDFmZGFhMTFmNGYzYTkxNWEzMTIyYzhhZThiM2YgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogOTYwLjBweDsKICAgICAgICAgICAgICAgIGhlaWdodDogNTEyLjBweDsKICAgICAgICAgICAgICAgIGxlZnQ6IDAuMCU7CiAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfNTc5MDFmZGFhMTFmNGYzYTkxNWEzMTIyYzhhZThiM2YiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgICAgICAgICAgCgogICAgICAgICAgICB2YXIgbWFwXzU3OTAxZmRhYTExZjRmM2E5MTVhMzEyMmM4YWU4YjNmID0gTC5tYXAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbWFwXzU3OTAxZmRhYTExZjRmM2E5MTVhMzEyMmM4YWU4YjNmJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtjZW50ZXI6IFszOC4zNTI0MywyMy4xMzk5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b29tOiA5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4Qm91bmRzOiBib3VuZHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXllcnM6IFtdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGRDb3B5SnVtcDogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl85OTZjMjQ4MzFlMDY0NmIyYWJmNzMyYmVhZGY2ZmYzMyA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgJ2h0dHBzOi8vY2FydG9kYi1iYXNlbWFwcy17c30uZ2xvYmFsLnNzbC5mYXN0bHkubmV0L2xpZ2h0X2FsbC97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzU3OTAxZmRhYTExZjRmM2E5MTVhMzEyMmM4YWU4YjNmKTsKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl84ZDQ4ZjNhNWY5NWI0MTNjYWNlMjY1ZmI3Nzk5NzZlMyA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM3Ljk3OTQ1LDIzLjcxNjIyXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfNTc5MDFmZGFhMTFmNGYzYTkxNWEzMTIyYzhhZThiM2YpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODdhMGEwNjdhMGQ1NGNmNzk1MTYzYTMxZDdlOWEwMTggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjM5OTM4Zjk4ZTI0NDcyMGJlODEwNTAzODhmMTQ3YzkgPSAkKCc8ZGl2IGlkPSJodG1sX2YzOTkzOGY5OGUyNDQ3MjBiZTgxMDUwMzg4ZjE0N2M5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BdGhlbnMgMzcuOTc5NDUyMy43MTYyMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODdhMGEwNjdhMGQ1NGNmNzk1MTYzYTMxZDdlOWEwMTguc2V0Q29udGVudChodG1sX2YzOTkzOGY5OGUyNDQ3MjBiZTgxMDUwMzg4ZjE0N2M5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfOGQ0OGYzYTVmOTViNDEzY2FjZTI2NWZiNzc5OTc2ZTMuYmluZFBvcHVwKHBvcHVwXzg3YTBhMDY3YTBkNTRjZjc5NTE2M2EzMWQ3ZTlhMDE4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzgzYzQyMWEzNjQxYzQ2NmZiM2VmZTY3YjcwZjkwOGYzID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzcuOTQwMDcsMjIuOTUxM10sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzU3OTAxZmRhYTExZjRmM2E5MTVhMzEyMmM4YWU4YjNmKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RlOTliNDRiMTgzZTRjMzdhZWVjZGEyZDRhOWYyYTBmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IzYTdiMTRlMzFlODRjYjc5ZDAxYWY4MjRlZDIwN2JlID0gJCgnPGRpdiBpZD0iaHRtbF9iM2E3YjE0ZTMxZTg0Y2I3OWQwMWFmODI0ZWQyMDdiZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q29yaW50aCAzNy45NDAwNzIyLjk1MTM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RlOTliNDRiMTgzZTRjMzdhZWVjZGEyZDRhOWYyYTBmLnNldENvbnRlbnQoaHRtbF9iM2E3YjE0ZTMxZTg0Y2I3OWQwMWFmODI0ZWQyMDdiZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyXzgzYzQyMWEzNjQxYzQ2NmZiM2VmZTY3YjcwZjkwOGYzLmJpbmRQb3B1cChwb3B1cF9kZTk5YjQ0YjE4M2U0YzM3YWVlY2RhMmQ0YTlmMmEwZik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl8zODI2MThjMDNiOGU0ZDdkOWI5YTZhYWYzNDE0OWZlNCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM4LjM1MjQzLDIzLjEzOTk1XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfNTc5MDFmZGFhMTFmNGYzYTkxNWEzMTIyYzhhZThiM2YpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzAxZjM2NzgxNjgyNGExZGJlNTBiNGFlNWY5ZjhkMWUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmVlN2IxZTNlMzViNGI3M2JiNjZhZDg4NTdiNmQzNzIgPSAkKCc8ZGl2IGlkPSJodG1sX2ZlZTdiMWUzZTM1YjRiNzNiYjY2YWQ4ODU3YjZkMzcyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DZW50cmFsIEdyZWVjZSAzOC4zNTI0MzIzLjEzOTk1PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83MDFmMzY3ODE2ODI0YTFkYmU1MGI0YWU1ZjlmOGQxZS5zZXRDb250ZW50KGh0bWxfZmVlN2IxZTNlMzViNGI3M2JiNjZhZDg4NTdiNmQzNzIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl8zODI2MThjMDNiOGU0ZDdkOWI5YTZhYWYzNDE0OWZlNC5iaW5kUG9wdXAocG9wdXBfNzAxZjM2NzgxNjgyNGExZGJlNTBiNGFlNWY5ZjhkMWUpOwoKICAgICAgICAgICAgCiAgICAgICAgCjwvc2NyaXB0Pg==\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x117dae128>"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# set up Folium and populate with coordinates\n",
    "\n",
    "basemap = folium.Map(location=main_center, zoom_start=9, tiles='cartodbpositron', width=960, height=512)\n",
    "\n",
    "for i, c in enumerate(top_coordinates):\n",
    "    folium.Marker([c[0], c[1]], popup='{} {}{}'.format(top_places[i], c[0], c[1])).add_to(basemap)\n",
    "    \n",
    "print('Map of relevant locations in Broneer et al.\\'s \"Ancient Corinth: A guide to the excavations\"')\n",
    "basemap"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
